﻿namespace NJQuery {
	using System;
	using System.ComponentModel;
	using System.ComponentModel.Design.Serialization;
	using System.Globalization;
	using System.Reflection;
	using System.Collections;

	/// <summary>
	/// Provides conversions for the <see cref="Icon"/> struct.
	/// </summary>
	public class IconConverter : TypeConverter {


		#region Static Methods

		private static InstanceDescriptor GetInstanceDescriptor(Icon value) {

			if(string.IsNullOrEmpty(value.CssClass)) return new InstanceDescriptor(
				typeof(Icon).GetField("None", BindingFlags.Public | BindingFlags.Static),
				null, true);

			return new InstanceDescriptor(
				typeof(Icon).GetConstructor(new Type[] { typeof(string) }),
				new object[] { value.CssClass });
		}

		#endregion


		#region Constructors

		/// <summary>
		/// Initializes a new <see cref="IconConverter"/> class.
		/// </summary>
		public IconConverter() { }

		#endregion


		#region Methods: Capabilities

		/// <summary>
		/// Returns whether or not this object supports a standard set of values that can be picked from a list, using the specified context.
		/// </summary>
		/// <param name="context">A <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
		/// <returns>Whether or not a standard set of values is supported.</returns>
		public override bool GetStandardValuesSupported(ITypeDescriptorContext context) {
			return true;
		}

		/// <summary>
		/// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context.
		/// </summary>
		/// <param name="context">A <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
		/// <param name="sourceType">The type of the object to be converted.</param>
		/// <returns>Whether or not the conversion can be performed.</returns>
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
			if(sourceType == typeof(string)) return true;
			return base.CanConvertFrom(context, sourceType);
		}

		/// <summary>
		/// Returns whether this converter can convert the object to the specified type, using the specified context.
		/// </summary>
		/// <param name="context">A <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
		/// <param name="destinationType">The target type of the object.</param>
		/// <returns>Whether or not the conversion can be performed.</returns>
		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
			if(destinationType == typeof(string)) return true;
			if(destinationType == typeof(InstanceDescriptor)) return true;
			return base.CanConvertTo(context, destinationType);
		}

		#endregion


		#region Methods: Perform tasks

		/// <summary>
		/// Returns a collection of standard values for the data type this converter is designed for when provided with a format context.
		/// </summary>
		/// <param name="context">A <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
		/// <returns>A collection of standard values.</returns>
		public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) {
			return new StandardValuesCollection(new Icon[] {
				Icon.Carat1N,
				Icon.Carat1NE,
				Icon.Carat1E,
				Icon.Carat1SE,
				Icon.Carat1S,
				Icon.Carat1SW,
				Icon.Carat1W,
				Icon.Carat1NW,
				Icon.Carat2NS,
				Icon.Carat2EW,
				Icon.Triangle1N,
				Icon.Triangle1NE,
				Icon.Triangle1E,
				Icon.TriangleSE,
				Icon.Triangle1S,
				Icon.Triangle1SW,
				Icon.Triangle1W,
				Icon.Triangle1NW,
				Icon.Triangle2NS,
				Icon.Triangle2EW,
				Icon.Arrow1N,
				Icon.Arrow1NE,
				Icon.Arrow1E,
				Icon.Arrow1SE,
				Icon.Arrow1S,
				Icon.Arrow1SW,
				Icon.Arrow1W,
				Icon.Arrow1NW,
				Icon.Arrow2NS,
				Icon.Arrow2NESW,
				Icon.Arrow2EW,
				Icon.Arrow2SENW,
				Icon.ArrowStop1N,
				Icon.ArrowStop1E,
				Icon.ArrowStop1S,
				Icon.ArrowStop1W,
				Icon.ArrowThick1N,
				Icon.ArrowThick1NE,
				Icon.ArrowThick1E,
				Icon.ArrowThick1SE,
				Icon.ArrowThick1S,
				Icon.ArrowThick1SW,
				Icon.ArrowThick1W,
				Icon.ArrowThick1NW,
				Icon.ArrowThick2NS,
				Icon.ArrowThick2NESW,
				Icon.ArrowThick2EW,
				Icon.ArrowThick2SENW,
				Icon.ArrowThickStop1N,
				Icon.ArrowThickStop1E,
				Icon.ArrowThickStop1S,
				Icon.ArrowThickStop1W,
				Icon.ArrowReturnThick1W,
				Icon.ArrowReturnThick1N,
				Icon.ArrowReturnThick1E,
				Icon.ArrowReturnThick1S,
				Icon.ArrowReturn1W,
				Icon.ArrowReturn1N,
				Icon.ArrowReturn1E,
				Icon.ArrowReturn1S,
				Icon.ArrowRefresh1W,
				Icon.ArrowRefresh1N,
				Icon.ArrowRefresh1E,
				Icon.ArrowRefresh1S,
				Icon.Arrow4,
				Icon.Arrow4Diag,
				Icon.ExtLink,
				Icon.NewWin,
				Icon.Refresh,
				Icon.Shuffle,
				Icon.TransferEW,
				Icon.TransferThickEW,
				Icon.FolderCollapsed,
				Icon.FolderOpen,
				Icon.Document,
				Icon.DocumentB,
				Icon.Note,
				Icon.MailClosed,
				Icon.MailOpen,
				Icon.Suitcase,
				Icon.Comment,
				Icon.Person,
				Icon.Print,
				Icon.Trash,
				Icon.Locked,
				Icon.Unlocked,
				Icon.Bookmark,
				Icon.Tag,
				Icon.Home,
				Icon.Flag,
				Icon.Calculator,
				Icon.Cart,
				Icon.Pencil,
				Icon.Clock,
				Icon.Disk,
				Icon.Calendar,
				Icon.ZoomIn,
				Icon.ZoomOut,
				Icon.Search,
				Icon.Wrench,
				Icon.Gear,
				Icon.Heart,
				Icon.Star,
				Icon.Link,
				Icon.Cancel,
				Icon.Plus,
				Icon.PlusThick,
				Icon.Minus,
				Icon.MinusThick,
				Icon.Close,
				Icon.CloseThick,
				Icon.Key,
				Icon.LightBulb,
				Icon.Scissors,
				Icon.Clipboard,
				Icon.Copy,
				Icon.Contact,
				Icon.Image,
				Icon.Video,
				Icon.Script,
				Icon.Alert,
				Icon.Info,
				Icon.Notice,
				Icon.Help,
				Icon.Check,
				Icon.Bullet,
				Icon.RadioOff,
				Icon.RadioOn,
				Icon.PinW,
				Icon.PinS,
				Icon.Play,
				Icon.Pause,
				Icon.SeekNext,
				Icon.SeekPrev,
				Icon.SeekEnd,
				Icon.SeekStart,
				Icon.Stop,
				Icon.Eject,
				Icon.VolumeOff,
				Icon.VolumeOn,
				Icon.Power,
				Icon.SignalDiag,
				Icon.Signal,
				Icon.Battery0,
				Icon.Battery1,
				Icon.Battery2,
				Icon.Battery3,
				Icon.CirclePlus,
				Icon.CircleMinus,
				Icon.CircleClose,
				Icon.CircleTriangleE,
				Icon.CircleTriangleS,
				Icon.CircleTriangleW,
				Icon.CircleTriangleN,
				Icon.CircleArrowE,
				Icon.CircleArrowS,
				Icon.CircleArrowW,
				Icon.CircleArrowN,
				Icon.CircleZoomIn,
				Icon.CircleZoomOut,
				Icon.CircleCheck,
				Icon.CircleSmallPlus,
				Icon.CircleSmallMinus,
				Icon.CircleSmallClose,
				Icon.SquareSmallPlus,
				Icon.SquareSmallMinus,
				Icon.SquareSmallClose,
				Icon.GripDottedVertical,
				Icon.GripDottedHorizontal,
				Icon.GripSolidVertical,
				Icon.GripSolidHorizontal,
				Icon.GripSmallDiagonalSE,
				Icon.GripDiagonalSE
			});
		}

		/// <summary>
		/// Converts the given object to the type of this converter, using the specified context and culture information.
		/// </summary>
		/// <param name="context">A <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
		/// <param name="culture">The <see cref="CultureInfo"/> to use as the current culture.</param>
		/// <param name="value">The object to be converted</param>
		/// <returns>The converted object.</returns>
		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {

			if(value == null) return new Icon();

			string text = value as string;
			if(text != null) return new Icon(text);

			return base.ConvertFrom(context, culture, value);
		}

		/// <summary>
		/// Converts the given object value to the specified type, using the specified context and culture information.
		/// </summary>
		/// <param name="context">A <see cref="ITypeDescriptorContext"/> that provides a format context.</param>
		/// <param name="culture">The <see cref="CultureInfo"/> to use as the current culture.</param>
		/// <param name="value">The object to be converted</param>
		/// <param name="destinationType">The <see cref="Type"/> to convert the value parameter to.</param>
		/// <returns>The converted object.</returns>
		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {

			if(destinationType == typeof(string))
				return ((Icon)value).ToString();

			if(destinationType == typeof(InstanceDescriptor))
				return GetInstanceDescriptor((Icon)value);

			return base.ConvertTo(context, culture, value, destinationType);
		}

		#endregion


	}

}